package org.gabryh.android.clipboard;


import static org.gabryh.android.clipboard.Provider.*;

import java.util.HashMap;

import android.content.ContentProvider;
import android.content.ContentProviderDatabaseHelper;
import android.content.ContentURIParser;
import android.content.ContentValues;
import android.content.QueryBuilder;
import android.content.Resources;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.net.ContentURI;
import android.util.Log;

public class ClipboardContentProvider extends ContentProvider{
	
    private static final String DATABASE_NAME 		= "clipboard.db";
    private static final int 	DATABASE_VERSION 	= 1;
    private static final String TABLE_NAME 			= "clipboard_items";
    
    private static final String COLUMN_ID 			= "_id";
    private static final String COLUMN_TIMESTAMP 	= "timestamp";

	private static final String DEFAULT_SORT_ORDER = COLUMN_TIMESTAMP + " DESC" ;
	
    private static final ContentURIParser URL_MATCHER;    
    private static final int ITEMS = 1;
    private static final int ITEM_ID = 2;
	private static final int CURRENT_ITEM = 3;
	private static final int SET_CURRENT_ITEM = 4;

	public static final String TAG = "Clipboard Provider" ;
    
    private static class DatabaseHelper extends ContentProviderDatabaseHelper {

        @Override
        public void onCreate(SQLiteDatabase db) {
        	ClipShell.appendMessage("Creating database");
        	db.execSQL(	"CREATE TABLE " + TABLE_NAME + " (" +
        				COLUMN_ID 			+ " INTEGER PRIMARY KEY AUTOINCREMENT," +
        				COLUMN_TIMESTAMP 	+ " INTEGER," +
        				COLUMN_TEXTUAL_DATA + " TEXT," + 
        				COLUMN_CONTENT_URI 	+ " TEXT);"
        	) ;
        	
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        	ClipShell.appendMessage("Updating Database");
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS notes");
            onCreate(db);																		
        }
    }

    private static HashMap<String, String> CLIPBOARD_ITEM_PROJECTION_MAP;

	private SQLiteDatabase mDB;
    
    @Override
    public boolean onCreate() {
        DatabaseHelper dbHelper = new DatabaseHelper();
        mDB = dbHelper.openDatabase(getContext(), DATABASE_NAME, null, DATABASE_VERSION);
        return (mDB == null) ? false : true;
    }


    public ClipboardContentProvider(){
		ClipShell.appendMessage("ClipboardContentProvider C-Tor");
	}
	
	@Override
	public ContentURI insert(ContentURI url, ContentValues initialValues) {
		// TODO Auto-generated method stub
		ClipShell.appendMessage("insert. url=" + url + ", initialValues=" + initialValues);
		
        long rowID;
        ContentValues values = new ContentValues(initialValues);;
        
        // Validation
        if( (! initialValues.containsKey(COLUMN_TEXTUAL_DATA)) &&
        	(! initialValues.containsKey(COLUMN_CONTENT_URI))){
            	throw new IllegalArgumentException("At least one data must be provided, textual Data or Content URI") ;
        }
            
        if(	initialValues.containsKey(COLUMN_ID) ||
    		initialValues.containsKey(COLUMN_TIMESTAMP) ) {
            	throw new IllegalArgumentException("ID or time stamp must no be provided") ;
        }
            
//        if (initialValues != null) {
//            values = new ContentValues(initialValues);
//        } else {
//            values = new ContentValues();
//        }

//        if (URL_MATCHER.match(url) != NOTES) {
//            throw new IllegalArgumentException("Unknown URL " + url);
//        }

        Long now = Long.valueOf(System.currentTimeMillis());
        Resources r = Resources.getSystem();

        // Put the time stamp. This will put the item on the top of the list 
        values.put(COLUMN_TIMESTAMP, now);

        if (! values.containsKey(COLUMN_CONTENT_URI)) {
            values.put(COLUMN_CONTENT_URI, "");
        }

        if (! values.containsKey(COLUMN_TEXTUAL_DATA)) {
            values.put(COLUMN_TEXTUAL_DATA, r.getString(android.R.string.untitled));
        }

        rowID = mDB.insert(TABLE_NAME, "", values);
        if (rowID > 0) {
            ContentURI uri = Provider.CONTENT_URI.addId(rowID);
            getContext().getContentResolver().notifyChange(uri, null);
            return uri;
        }

        throw new SQLException("Failed to insert row into " + url);

	}
	
	@Override
	public int update(ContentURI url, ContentValues values, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		ClipShell.appendMessage("update. url=" + url + ", values=" + values + ", selection=" + selection + ", selectionArgs=" + selectionArgs);
		
		int count;
        switch (URL_MATCHER.match(url)) {
		    case ITEMS:
		    case CURRENT_ITEM:
		    case ITEM_ID :
	        	throw new IllegalArgumentException("Only SET_CURRENT_ITEM url is allowed");
	
	        case SET_CURRENT_ITEM:
	            String idSegment = url.getPathSegment(1);
	            values = new ContentValues() ;
	            Long now = Long.valueOf(System.currentTimeMillis());
	            values.put(COLUMN_TIMESTAMP, now) ;
	            count = mDB.update(TABLE_NAME, values, COLUMN_ID + "=" + idSegment, null) ;                           
	            break;
	
	        default:
	            throw new IllegalArgumentException("Unknown URL " + url);
        }

        getContext().getContentResolver().notifyChange(url, null);
        return count;
	}
	
	@Override
	public String getType(ContentURI uri) {
		// TODO Auto-generated method stub
		ClipShell.appendMessage("getType");
//        switch (URL_MATCHER.match(url)) {
//	        case ITEMS:
//	        	return "vnd.android.cursor.dir/vnd.google.note";
//		    case CURRENT_ITEM:
//		    case SET_CURRENT_ITEM :
//	        	throw new IllegalArgumentException("Only ITEM_ID url is allowed");
//	
//	        case ITEM_ID:
//	            String idSegment = url.getPathSegment(1);
//	            count = mDB.delete(TABLE_NAME, COLUMN_ID + "=" + idSegment, null) ; 
//	            break;
//	
//	        default:
//	        	throw new IllegalArgumentException("Unknown URL " + url);
//        }
		return null ;
		
	}
	
	@Override
	public int delete(ContentURI url, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		ClipShell.appendMessage("delete");
		
		int count;
        switch (URL_MATCHER.match(url)) {
		    case ITEMS:
		    case CURRENT_ITEM:
		    case SET_CURRENT_ITEM :
	        	throw new IllegalArgumentException("Only ITEM_ID url is allowed");
	
	        case ITEM_ID:
	            String idSegment = url.getPathSegment(1);
	            count = mDB.delete(TABLE_NAME, COLUMN_ID + "=" + idSegment, null) ; 
	            break;
	
	        default:
	            throw new IllegalArgumentException("Unknown URL " + url);
        }

        getContext().getContentResolver().notifyChange(url, null);
        return count;	
    }
	
	@Override
	public Cursor query(ContentURI url, String[] projection,
			String selection, String[] selectionArgs, String groupBy,
			String having, String sortOrder) {
		// TODO Auto-generated method stub
		ClipShell.appendMessage("query. url=" + url);
		
		QueryBuilder qb = new QueryBuilder();

		qb.setProjectionMap(CLIPBOARD_ITEM_PROJECTION_MAP);
		qb.setTables(TABLE_NAME);
		
		switch (URL_MATCHER.match(url)) {
	        case SET_CURRENT_ITEM :
	        	throw new IllegalArgumentException("SET_CURRENT_ITEM url is not allowed");
	        	
	        case ITEMS:
	            break;
	
	        case ITEM_ID:
	            qb.appendWhere("_id=" + url.getPathSegment(1));
	            break;
	
	        case CURRENT_ITEM:
	            break;
	
	        default:
	        	throw new IllegalArgumentException("Unknown URL " + url);
        }

		String[] emptyStringArray = new String[]{} ;
        Cursor c = qb.query(mDB, emptyStringArray, "", emptyStringArray, "", "", DEFAULT_SORT_ORDER);
        c.setNotificationUri(getContext().getContentResolver(), url);
        return c;
		
	}
	
    static {
        URL_MATCHER = new ContentURIParser(ContentURIParser.NO_MATCH);
        URL_MATCHER.addURI("org.gabryh.android.clipboard", "list", ITEMS);
        URL_MATCHER.addURI("org.gabryh.android.clipboard", "list/#", ITEM_ID);
        URL_MATCHER.addURI("org.gabryh.android.clipboard", "current", CURRENT_ITEM);
        URL_MATCHER.addURI("org.gabryh.android.clipboard", "setCurrent/#", SET_CURRENT_ITEM);
        
        CLIPBOARD_ITEM_PROJECTION_MAP = new HashMap<String, String>();
        CLIPBOARD_ITEM_PROJECTION_MAP.put(COLUMN_ID, COLUMN_ID);
        CLIPBOARD_ITEM_PROJECTION_MAP.put(COLUMN_TIMESTAMP, COLUMN_TIMESTAMP);
        CLIPBOARD_ITEM_PROJECTION_MAP.put(COLUMN_TEXTUAL_DATA, COLUMN_TEXTUAL_DATA);
        CLIPBOARD_ITEM_PROJECTION_MAP.put(COLUMN_CONTENT_URI, COLUMN_CONTENT_URI);
    }	
	
}
